package answercard;

import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.util.*;

import static org.opencv.core.CvType.CV_8U;

/**
 * @author chenkn
 * since 2018/12/13
 */
public class TaskTest {
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    static void readImage(String image) {
        Mat img = Imgcodecs.imread(image);//读取图像
        Mat srcImage2 = new Mat();
        Mat srcImage3 = new Mat();
        Mat srcImage4 = new Mat();
        Mat srcImage5 = new Mat();
        //图片变成灰度图片,它将图像从一个颜色空间转换为另一个颜色空间。
        Imgproc.cvtColor(img, srcImage2, Imgproc.COLOR_RGB2GRAY);
        Imgcodecs.imwrite("D://result2.jpg", srcImage2);
        //图片二值化
        Imgproc.adaptiveThreshold(srcImage2, srcImage3, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 255, 1);
        Imgcodecs.imwrite("D://result3.jpg", srcImage3);
        //确定腐蚀和膨胀核的大小
        Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(4.5, 4.5));
        //腐蚀操作
        Imgproc.erode(srcImage3, srcImage4, element);
        Imgcodecs.imwrite("D://result4.jpg", srcImage4);
        //膨胀操作
        Imgproc.dilate(srcImage4, srcImage5, element);
        Imgcodecs.imwrite("D://result5.jpg", srcImage5);
        //确定选择题卡的ROI区域,xywh表示图片像素坐标
//        Mat imag_ch1 = srcImage5.submat(new Rect(1591, 819, 1156, 878));
        Mat imag_ch1 = srcImage5.submat(new Rect(1600, 836, 1073, 853));
        Imgcodecs.imwrite("D://imag_ch1.jpg", imag_ch1);//获取选择题轮廓

        Vector<MatOfPoint> chapter1 = new Vector<>();
        Mat hierarchy = new Mat(imag_ch1.rows(), imag_ch1.cols(), CvType.CV_8UC1, new Scalar(0));
        Imgproc.findContours(imag_ch1, chapter1, hierarchy, 0, 2);//查找轮廓
        System.out.println("chapter1.size() = " + chapter1.size());


        //new一个 矩形集合 用来装 轮廓
        List<RectComp> rectCompList = new ArrayList<>();
        for (int i = 0; i < chapter1.size(); i++) {
            MatOfPoint matOfPoint = chapter1.get(i);
            Rect rm = Imgproc.boundingRect(matOfPoint);
            RectComp ti = new RectComp(rm);
            Mat result = imag_ch1.clone();
            Imgproc.drawContours(result, chapter1, i, new Scalar(160), 3);
            Imgcodecs.imwrite("D://ask//ask"+i+".jpg", result);//获取选择题轮廓
            //把轮廓宽度区间在 50 - 80 范围内的轮廓装进矩形集合
            if (ti.rm.width > 50 ) {
                rectCompList.add(ti);
            }
        }
        System.out.println(rectCompList.size());
        System.out.println("rectCompList = " + rectCompList);

        TreeMap<Integer,String> listenAnswer = new TreeMap<>();
        for (int i = 0; i < rectCompList.size(); i++) {
            RectComp rect = rectCompList.get(0);
            System.out.println("rect.getRm() = " + rect.getRm());
            if (rect.getRm().area() > 300) {
                if (rect.getRm().x < 150) {
                    listenAnswer.put(i, "A");
                } else if ((rect.getRm().x > 150) && (rect.getRm().x < 250)) {
                    listenAnswer.put(i, "B");
                } else if ((rect.getRm().x > 250) && (rect.getRm().x < 350)) {
                    listenAnswer.put(i, "C");
                } else if (rect.getRm().x > 350) {
                    listenAnswer.put(i, "D");
                }
            } else {
                listenAnswer.put(i, "未填写");
            }
        }
        Mat result = new Mat(imag_ch1.size(), CvType.CV_8U, new Scalar(255));
        Imgproc.drawContours(result, chapter1, 1, new Scalar(0), 2);//识别第一个轮廓
        Imgcodecs.imwrite("D://result_6.jpg", result);
        StringBuilder resultValue = new StringBuilder("最终结果：试题编号-答案 ");
        for (Integer key : listenAnswer.keySet()) {
            resultValue.append("【").append(key + 1).append(":").append(listenAnswer.get(key)).append("】");
        }
        System.out.println("resultValue = " + resultValue);
        System.exit(0);
        Mat result6 = new Mat(imag_ch1.size(), CV_8U, new Scalar(255));
        Imgproc.drawContours(result6, chapter1, 1, new Scalar(0), 2);//识别第一个轮廓

//        Imgproc.rectangle(result6, new Rect(0,0,1500,1000), new Scalar(0, 255, 0));
        Imgcodecs.imwrite("D://result6.jpg", result6);



        Imgproc.GaussianBlur(result6, result6, new Size(3, 3), 0);
        System.out.println("result6.cols()  = " + result6.cols());
        System.out.println("result6.rows() = " + result6.rows());
        Mat askImage = new Mat(result6, new Rect(result6.cols() - 1400, 0, 1100, result6.rows() - 2300));
        Imgcodecs.imwrite("D://result7.jpg", askImage);

        //new一个 矩形集合 用来装 轮廓
        List<RectComp> rectCompList2 = new ArrayList<>();
        for (int i = 0; i < chapter1.size(); i++) {
            MatOfPoint matOfPoint = chapter1.get(i);
            Rect rm = Imgproc.boundingRect(matOfPoint);
            RectComp ti = new RectComp(rm);
            //把轮廓宽度区间在 50 - 80 范围内的轮廓装进矩形集合
            if (ti.rm.width > 50 && ti.rm.width < 1060) {
                rectCompList2.add(ti);
            }
        }
        System.out.println(rectCompList2.size());
//        System.exit(0);
        //new一个 map 用来存储答题卡上填的答案 (A\B\C\D)
        TreeMap<Integer, String> listenAnswer2 = new TreeMap<>();
        //按 X轴 对listenAnswer进行排序
        rectCompList.sort((o1, o2) -> {
            if (o1.rm.x > o2.rm.x) {
                return 1;
            }
            if (o1.rm.x == o2.rm.x) {
                return 0;
            }
            if (o1.rm.x < o2.rm.x) {
                return -1;
            }
            return -1;
        });

        //根据 Y轴 确定被选择答案 (A\B\C\D)
        for (RectComp rc : rectCompList) {
            for (int h = 0; h < 7; h++) {
                if ((rc.rm.contains(new Point(rc.rm.x + 20, 115 + (320 * h))))) {
                    for (int w = 0; w < 4; w++) {
                        if (rc.rm.contains(new Point(55 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(1 + (20 * h) + (5 * w), "A");
                        } else if (rc.rm.contains(new Point(135 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(2 + (20 * h) + (5 * w), "A");
                        } else if (rc.rm.contains(new Point(215 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(3 + (20 * h) + (5 * w), "A");
                        } else if (rc.rm.contains(new Point(300 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(4 + (20 * h) + (5 * w), "A");
                        } else if (rc.rm.contains(new Point(380 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(5 + (20 * h) + (5 * w), "A");
                        }
                    }
                } else if ((rc.rm.contains(new Point(rc.rm.x + 20, 165 + (320 * h))))) {
                    for (int w = 0; w < 4; w++) {
                        if (rc.rm.contains(new Point(55 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(1 + (20 * h) + (5 * w), "B");
                        } else if (rc.rm.contains(new Point(135 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(2 + (20 * h) + (5 * w), "B");
                        } else if (rc.rm.contains(new Point(215 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(3 + (20 * h) + (5 * w), "B");
                        } else if (rc.rm.contains(new Point(300 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(4 + (20 * h) + (5 * w), "B");
                        } else if (rc.rm.contains(new Point(380 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(5 + (20 * h) + (5 * w), "B");
                        }
                    }
                } else if ((rc.rm.contains(new Point(rc.rm.x + 20, 220 + (320 * h))))) {
                    for (int w = 0; w < 4; w++) {
                        if (rc.rm.contains(new Point(55 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(1 + (20 * h) + (5 * w), "C");
                        } else if (rc.rm.contains(new Point(135 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(2 + (20 * h) + (5 * w), "C");
                        } else if (rc.rm.contains(new Point(215 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(3 + (20 * h) + (5 * w), "C");
                        } else if (rc.rm.contains(new Point(300 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(4 + (20 * h) + (5 * w), "C");
                        } else if (rc.rm.contains(new Point(380 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(5 + (20 * h) + (5 * w), "C");
                        }
                    }
                } else if ((rc.rm.contains(new Point(rc.rm.x + 20, 275 + (320 * h))))) {
                    for (int w = 0; w < 4; w++) {
                        if (rc.rm.contains(new Point(55 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(1 + (20 * h) + (5 * w), "D");
                        } else if (rc.rm.contains(new Point(135 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(2 + (20 * h) + (5 * w), "D");
                        } else if (rc.rm.contains(new Point(215 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(3 + (20 * h) + (5 * w), "D");
                        } else if (rc.rm.contains(new Point(300 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(4 + (20 * h) + (5 * w), "D");
                        } else if (rc.rm.contains(new Point(380 + (500 * w), rc.rm.y))) {
                            listenAnswer.put(5 + (20 * h) + (5 * w), "D");
                        }
                    }
                }
            }
        }

        Iterator iter = listenAnswer.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();
            Object key = entry.getKey();
            Object val = entry.getValue();
            System.out.println("第" + key + "题,分数:" + val);
        }
    }

    static void process(String image){
        Mat sourceMage = Imgcodecs.imread(image,0);//读取图像
        System.out.println("sourceMage.width() = " + sourceMage.width());
        System.out.println("sourceMage.height() = " + sourceMage.height());
        Mat srcImage0 = new Mat();
        Mat srcImage1 = new Mat();
        Mat srcImage2 = new Mat();
        Imgproc.cvtColor(sourceMage, srcImage0, Imgproc.COLOR_RGB2GRAY);//灰度图像
        Imgcodecs.imwrite("D://result0.jpg", srcImage0);
        //图片二值化
        Imgproc.adaptiveThreshold(srcImage0, srcImage1, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 255, 1);
        Imgcodecs.imwrite("D://result3.jpg", srcImage1);


    }


    public static void main(String[] args) {
        String src = "D:\\eclipse_wk\\opencv-master\\img\\a5.jpg";
        readImage(src);
//        processImage(src);
    }
}
